Skip to content

[libc++] Fix std::variant evaluating template arguments too eagerly #151028

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Aug 11, 2025

Conversation

philnik777
Copy link
Contributor

@philnik777 philnik777 commented Jul 28, 2025

This has been reported in #116709 (comment).

Fixes #151328

Copy link

github-actions bot commented Jul 28, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

@philnik777 philnik777 marked this pull request as ready for review July 30, 2025 12:44
@philnik777 philnik777 requested a review from a team as a code owner July 30, 2025 12:44
@llvmbot llvmbot added the libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. label Jul 30, 2025
@llvmbot
Copy link
Member

llvmbot commented Jul 30, 2025

@llvm/pr-subscribers-libcxx

Author: Nikolas Klauser (philnik777)

Changes

Full diff: https://github.com/llvm/llvm-project/pull/151028.diff

2 Files Affected:

  • (modified) libcxx/include/__type_traits/invoke.h (+6-5)
  • (added) libcxx/test/std/test.pass.cpp (+24)
diff --git a/libcxx/include/__type_traits/invoke.h b/libcxx/include/__type_traits/invoke.h
index 5ff2efbe5faaf..d7fa979bcc5e7 100644
--- a/libcxx/include/__type_traits/invoke.h
+++ b/libcxx/include/__type_traits/invoke.h
@@ -22,6 +22,7 @@
 #include <__type_traits/is_same.h>
 #include <__type_traits/is_void.h>
 #include <__type_traits/nat.h>
+#include <__type_traits/type_identity.h>
 #include <__type_traits/void_t.h>
 #include <__utility/declval.h>
 #include <__utility/forward.h>
@@ -67,20 +68,20 @@ _LIBCPP_BEGIN_NAMESPACE_STD
 
 #if __has_builtin(__builtin_invoke)
 
-template <class... _Args>
-using __invoke_result_t _LIBCPP_NODEBUG = decltype(__builtin_invoke(std::declval<_Args>()...));
-
 template <class, class... _Args>
 struct __invoke_result_impl {};
 
 template <class... _Args>
-struct __invoke_result_impl<__void_t<__invoke_result_t<_Args...> >, _Args...> {
-  using type _LIBCPP_NODEBUG = __invoke_result_t<_Args...>;
+struct __invoke_result_impl<__void_t<decltype(__builtin_invoke(std::declval<_Args...>()))>, _Args...> {
+  using type _LIBCPP_NODEBUG = decltype(__builtin_invoke(std::declval<_Args...>()));
 };
 
 template <class... _Args>
 using __invoke_result _LIBCPP_NODEBUG = __invoke_result_impl<void, _Args...>;
 
+template <class... _Args>
+using __invoke_result_t _LIBCPP_NODEBUG = typename __invoke_result<_Args...>::type;
+
 template <class... _Args>
 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR __invoke_result_t<_Args...> __invoke(_Args&&... __args)
     _NOEXCEPT_(noexcept(__builtin_invoke(std::forward<_Args>(__args)...))) {
diff --git a/libcxx/test/std/test.pass.cpp b/libcxx/test/std/test.pass.cpp
new file mode 100644
index 0000000000000..1ff28c481e6ee
--- /dev/null
+++ b/libcxx/test/std/test.pass.cpp
@@ -0,0 +1,24 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include <variant>
+#include <utility>
+
+struct Nullable {
+  template <typename V> Nullable(V);
+};
+
+struct Matcher {
+  Matcher();
+  Matcher(std::variant<Nullable>);
+};
+
+void f() {
+  Matcher vec;
+  Matcher m = std::move(vec);
+}

@frederick-vs-ja frederick-vs-ja added this to the LLVM 21.x Release milestone Jul 31, 2025
@github-project-automation github-project-automation bot moved this to Needs Triage in LLVM Release Status Jul 31, 2025
@philnik777 philnik777 force-pushed the invoke_less_eager_instantiation branch from 6153d21 to 10260aa Compare July 31, 2025 08:42
@philnik777 philnik777 changed the title [libc++] Fix std::variant/std::invoke too eager instantiation [libc++] Fix std::variant evaluating template arguments too eagerly Jul 31, 2025
@@ -1182,13 +1182,21 @@ public:
_LIBCPP_HIDE_FROM_ABI constexpr variant(const variant&) = default;
_LIBCPP_HIDE_FROM_ABI constexpr variant(variant&&) = default;

template < class _Arg,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would suggest this instead, which is easier to read IMO:

template <class _Arg, class _DependentArg = enable_if_t<
    !is_same_v<__remove_cvref_t<_Arg>, variant> &&
    !__is_inplace_type<__remove_cvref_t<_Arg>>::value &&
    !__is_inplace_index<__remove_cvref_t<_Arg>>::value,
    _Arg
  >,
  class _Tp = __variant_detail::__best_match_t<_DependentArg, _Types...>,
  size_t _Ip = __find_detail::__find_unambiguous_index_sfinae<_Tp, _Types...>::value,
  enable_if_t<is_constructible_v<_Tp, _Arg>, int> = 0
>

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't work. I'm going with the original for now and we can take another look later.

Copy link
Member

@ldionne ldionne left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM with comments applied and assuming CI is green! Thanks!

@github-project-automation github-project-automation bot moved this from Needs Triage to Needs Merge in LLVM Release Status Jul 31, 2025
@tru tru moved this from Needs Merge to Needs Backport PR in LLVM Release Status Aug 1, 2025
@philnik777 philnik777 force-pushed the invoke_less_eager_instantiation branch 3 times, most recently from 2627e8b to 9c7f246 Compare August 5, 2025 08:30
@philnik777 philnik777 force-pushed the invoke_less_eager_instantiation branch from 9c7f246 to dc2d9e7 Compare August 7, 2025 07:26
@github-project-automation github-project-automation bot moved this from Needs Backport PR to Needs Merge in LLVM Release Status Aug 11, 2025
@ldionne ldionne merged commit f5f5824 into llvm:main Aug 11, 2025
69 of 76 checks passed
@github-project-automation github-project-automation bot moved this from Needs Merge to Done in LLVM Release Status Aug 11, 2025
@ldionne
Copy link
Member

ldionne commented Aug 11, 2025

/cherry-pick f5f5824

@llvmbot
Copy link
Member

llvmbot commented Aug 11, 2025

/pull-request #153064

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.
Projects
Development

Successfully merging this pull request may close these issues.

[libc++] Regression with std::variant move construction
4 participants